#include <conio.h>
#include "stack.h"
#include "FONT.H"
#include "INPUT.H"

//The scanline floodfill algorithm using our own stack routines, faster
void floodFillScanlineStack(int x, int y, int fill_color)
{
	Stack S;
	infotype P;
	infotype X;
    int tempY; 
	int target_color;
    boolean spanLeft, spanRight;
	
	target_color = getPixel(x,y);
    if(target_color == fill_color) return;
    CreateEmpty(&S);
    
	P.x = x;
	P.y = y;
    if(!PushFill(&S,P)) return;
    
    while(PopFill(&S,&P))
    {    
        tempY = P.y;
        while(tempY >= 0 && getPixel(P.x,tempY) == target_color) tempY--;
        tempY++;
        spanLeft = spanRight = 0;
        while(tempY < SCREEN_HEIGHT && getPixel(P.x,tempY) == target_color )
        {
            putPixel(P.x,tempY,fill_color);
            if(!spanLeft && P.x > 0 && getPixel(P.x-1,tempY) == target_color) 
            {
				X.x = P.x - 1;
				X.y = tempY;
                if(!PushFill(&S,X)) return;
                spanLeft = 1;
            }
            else if(spanLeft && P.x > 0 && getPixel(P.x-1,tempY) != target_color)
            {
                spanLeft = 0;
            }
            if(!spanRight && P.x < SCREEN_WIDTH - 1 && getPixel(P.x+1,tempY) == target_color) 
            {
				X.x = P.x + 1;
				X.y = tempY;
                if(!PushFill(&S,X)) return;
                spanRight = 1;
            }
            else if(spanRight && P.x < SCREEN_WIDTH - 1 && getPixel(P.x+1,tempY) != target_color)
            {
                spanRight = 0;
            } 
            tempY++;
        }
    }
}

void LineFill(int x1, int x2, int y, 
        byte fill_color, byte target_color)
{
    int xL,xR;
    if( y < 0 || SCREEN_HEIGHT < y )
        return;
    for( xL = x1; xL >= 0; --xL ) { // scan left

        if( getPixel(xL,y) != target_color )
            break;
        putPixel(xL,y,fill_color);
    }
    if( xL < x1 ) {
        LineFill(xL, x1, y-1, fill_color, target_color); // fill child

        LineFill(xL, x1, y+1, fill_color, target_color); // fill child

        ++x1;
    }
    for( xR = x2;  xR <= SCREEN_WIDTH; ++xR ) { // scan right

        if( getPixel(xR,y) !=  target_color )
            break;
        putPixel(xR,y,fill_color);
    }
    if(  xR > x2 ) {
        LineFill(x2, xR, y-1, fill_color, target_color); // fill child

        LineFill(x2, xR, y+1, fill_color, target_color); // fill child

        --x2;
    }
    for( xR = x1; xR <= x2 && xR <= SCREEN_WIDTH; ++xR ) {  // scan betweens

        if( getPixel(xR,y) == target_color )
            putPixel(xR,y,fill_color);
        else {
            if( x1 < xR ) {
                // fill child

                LineFill(x1, xR-1, y-1, fill_color, target_color);
                // fill child

                LineFill(x1, xR-1, y+1, fill_color, target_color);
                x1 = xR;
            }
            // Note: This function still works if this step is removed.

            for( ; xR <= x2 && xR <= SCREEN_WIDTH; ++xR) { // skip over border

                if( getPixel(xR,y) == target_color ) {
                    x1 = xR--;
                    break;
                }
            }
        }
    }
}

void SeedFill(int x, int y, byte fill_color)
{
    byte target_color = getPixel(x,y);
    if( fill_color != target_color )
        LineFill(x,x,y,fill_color,target_color);
}

void getFillArea(Stack *S, int x, int y, byte target_color, byte fill_color) {
	infotype P;
	P.x = x;
	P.y = y;
	if (Contains(*S,P) == FALSE && x >= 0 && y >= 0 && x <= SCREEN_WIDTH && y <= SCREEN_HEIGHT) {
		byte currColor = getPixel(x,y);
		if (currColor == target_color &&
			currColor != fill_color) {
			PushUnik(&(*S),P);
			// printf("%d,%d ",x,y);
			getFillArea(&(*S), x+1, y, target_color, fill_color);
			//getFillArea(&(*S), x-1, y, target_color, fill_color);
			getFillArea(&(*S), x, y+1, target_color, fill_color);
			//getFillArea(&(*S), x, y-1, target_color, fill_color);
		}
	}
}

void doFill(Stack S,byte fill_color) {
	infotype P;
	while (!IsEmpty(S)) {
		Pop(&S,&P);
		putPixel(P.x,P.y,fill_color);
	}
}

void floodFill(int x, int y, byte target_color, byte fill_color){
	Stack S;
	infotype A;
	// infotype B;
	byte currColor;
	
	// A.x = x;
	// A.y = y;
	CreateEmpty(&S);
	// currColor = getPixel(A.x,A.y);
	// if (currColor==target_color && 
		// currColor!=fill_color &&
		// A.x>=0 && A.x<SCREEN_WIDTH && 
		// A.y>=0 && A.y<SCREEN_HEIGHT){ 
		// Push(&S, A);
	// }
	// while (!IsEmpty(S)){
		// Pop(&S, &A);
		// putPixel(A.x,A.y,fill_color);
		// // redraw();
		// A.x++;
		// currColor = getPixel(A.x,A.y);
		// if (currColor==target_color && 
			// currColor!=fill_color &&
			// A.x>=0 && A.x<SCREEN_WIDTH && 
			// A.y>=0 && A.y<SCREEN_HEIGHT){ 
			// PushUnik(&S, A);
		// } else {
			// A.x--;
			// A.y++;
			// currColor = getPixel(A.x,A.y);
			// if (currColor==target_color && 
				// currColor!=fill_color &&
				// A.x>=0 && A.x<SCREEN_WIDTH && 
				// A.y>=0 && A.y<SCREEN_HEIGHT){ 
				// PushUnik(&S, A);
			// } else {
				// A.x--;
				// A.y--;
				// currColor = getPixel(A.x,A.y);
				// if (currColor==target_color && 
					// currColor!=fill_color &&
					// A.x>=0 && A.x<SCREEN_WIDTH && 
					// A.y>=0 && A.y<SCREEN_HEIGHT){ 
					// PushUnik(&S, A);
				// } else {
					// A.x++;
					// A.y--;
					// currColor = getPixel(A.x,A.y);
					// if (currColor==target_color && 
						// currColor!=fill_color &&
						// A.x>=0 && A.x<SCREEN_WIDTH && 
						// A.y>=0 && A.y<SCREEN_HEIGHT){ 
						// PushUnik(&S, A);
					// }
				// }
			// }
		// }
	// }
	
	// floodFillScanlineStack(S, x, y, fill_color, target_color);
	// A.x = 1;
	// A.y = 2;
	// // Push(&S,A);
	// if (Contains(S,A) == TRUE) {
		// printf("TRUE");
	// } else {
		// printf("FALSE");
	// }
	// printf("All : %d",NbElmt(S));
	free(&S);
	// if (getPixel(x,y)==target_color && getPixel(x,y)!=fill_color
		// && x>=0 && x<=SCREEN_WIDTH && y>=0 && y<=SCREEN_HEIGHT){ 
		// putPixel(x,y,fill_color);
		// floodFill(x,y-1,target_color,fill_color); //atas
		// floodFill(x+1,y,target_color,fill_color); //kanan
		// floodFill(x-1,y,target_color,fill_color); //kiri
		// floodFill(x,y+1,target_color,fill_color); //bawah
	// }
}



int main()
{
	MouseState prevMouseState;
	MouseState currMouseState;
	boolean mouseOn;
	int tInput;
	byte numButtons;
	byte fillColor = 0;
	Fonts fonts;
	boolean fontEnable = loadFonts("FONT.FNT", &fonts);
	
	setMode(VGA_MODE);
	mouseOn = initMouse(&numButtons);	
	if(mouseOn){
		prevMouseState = getMouseState();
		showMouseCursor();
	}
	while(TRUE){
		setBackground(LIGHT_BLUE);
		redraw();
		if(mouseOn){
			currMouseState = getMouseState();
			drawFont(fonts, 97, 100, 100, RED);
			if (((prevMouseState.buttonState&1)==1) && ((currMouseState.buttonState&1)==0)) {
				floodFillScanlineStack(currMouseState.x,currMouseState.y,RED);
				redraw();
			}
			prevMouseState = currMouseState;
		}
		if(kbhit()){
			tInput = getKey();
			/* Escape to quit*/
			if(tInput == 27){
				break;
			}	
		}
		// redraw();		
		delay(33);
	}	
	setMode(TEXT_MODE);
	return EXIT_SUCCESS;
	// int tInput;
// //	boolean fill=FALSE;
	// // int x = 0;
	// // int y = 0;
	// // int i;	
	// // int state = 0;
	
	// // Fonts fonts;
	// //boolean fontEnable = loadFonts("FONT.FNT", &fonts);
	// setMode(VGA_MODE);
	// setBackground(LIGHT_BLUE);
	// //drawRectangle(50,50,150,150,RED);
	// //drawCircle(70,30,28,YELLOW);
	// redraw();
	// while(TRUE){
		// if(kbhit()){
			// tInput = getKey();
			// if(tInput == 27){
				// break;
			// }
			// if(tInput == 13){
				// // printf("Start\n");
				// // floodFill(70,30,LIGHT_BLUE,RED);
				// floodFillScanlineStack(60,60,LIGHT_BLUE,RED);
				// //SeedFill(60,60,RED);
				// redraw();
			// }
		// }		
						
		// // if(fontEnable){		
			// // drawFont(fonts,'A', 0, 0, RED);
		// // }
		
		
		// // drawRectangle(10,10,20,20,RED);
		
		// //drawRectangle(0,150,20,20,RED);
		// //drawRectangle(30,30,150,150,BLUE);
		// //drawCircle(70,30,28,YELLOW);
		// // if (fill > 0){
			// // //floodFill(15,15,LIGHT_BLUE,RED);
			
		// // } 
		
		
		// //redraw();
		// delay(33);
	// }
	// //freeFonts(&fonts);
	// setMode(TEXT_MODE);	
	// return EXIT_SUCCESS;
}